/*
 * Copyright (C) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Downloader } from '../bitmap/download/Downloader'
import { BitmapCache } from './core/BitmapCache'
import { BitmapCacheListener } from '../bitmap/BitmapCacheListener'
import { BitmapCacheManagementTask } from '../task/BitmapCacheManagementTask';
import { DefaultDownloader } from './download/DefaultDownloader';

export class BitmapGlobalConfig {
    diskCachePath: string = "xBitmapCache";
    MIN_MEMORY_CACHE_SIZE: number = 1024 * 1024 * 2;
    memoryCacheSize: number = 1024 * 4;
    MIN_DISK_CACHE_SIZE: number = 1024 * 1024 * 10;
    diskCacheSize: number = 1024 * 1024 * 50;
    memoryCacheEnabled = true;
    diskCacheEnabled = true;
    downloader: Downloader;
    bitmapCache: BitmapCache;
    DEFAULT_POOL_SIZE: number = 5;
    defaultCacheExpiry: number = 60 * 1;
    defaultConnectTimeout: number = 1000 * 15;
    defaultReadTimeout: number = 1000 * 15;
    bitmapCacheListener: BitmapCacheListener;
    appVersion: string
    mContext: any;

    constructor(diskCachePath: string) {
        this.diskCachePath = diskCachePath;
        this.initBitmapCache();
    }

    public static getInstance(diskCachePath: string): BitmapGlobalConfig {

        if (null == diskCachePath || diskCachePath.length == 0) {
            diskCachePath = "xBitmapCache";
        }

        let config = new BitmapGlobalConfig(diskCachePath);
        return config;

    }

    public getDiskCachePath(): string {
        if (this.diskCachePath == null || this.diskCachePath == undefined || this.diskCachePath.length == 0) {
            this.diskCachePath = "xBitmapCache";
        }
        return this.diskCachePath;
    }

    setDiskCachePath(value: string) {
        this.diskCachePath = value;
    }

    public getDownloader(): Downloader {
        if (this.downloader == null) {
            this.downloader = new DefaultDownloader();
        }
        this.downloader.setContext(this.mContext);
        this.downloader.setDefaultExpiry(this.getDefaultCacheExpiry());
        this.downloader.setDefaultConnectTimeout(this.getDefaultConnectTimeout());
        this.downloader.setDefaultReadTimeout(this.getDefaultReadTimeout());
        return this.downloader;
    }

    public setDownloader(downloader: Downloader): void {
        downloader = downloader;
    }

    public getDefaultCacheExpiry(): number {
        return this.defaultCacheExpiry;
    }

    public setDefaultCacheExpiry(defaultCacheExpiry: number): void {
        this.defaultCacheExpiry = defaultCacheExpiry;
    }

    public getDefaultConnectTimeout(): number {
        return this.defaultConnectTimeout;
    }

    public setDefaultConnectTimeout(defaultConnectTimeout: number): void {
        this.defaultConnectTimeout = defaultConnectTimeout;
    }

    public getDefaultReadTimeout(): number {
        return this.defaultReadTimeout;
    }

    public setDefaultReadTimeout(defaultReadTimeout: number): void {
        this.defaultReadTimeout = defaultReadTimeout;
    }

    public getBitmapCache(): BitmapCache {
        if (this.bitmapCache == null) {
            this.bitmapCache = new BitmapCache(this);
        }
        return this.bitmapCache;
    }

    public getMemoryCacheSize(): number {
        return this.memoryCacheSize;
    }

    public setMemoryCacheSize(memoryCacheSize: number): void {
        if (memoryCacheSize >= this.MIN_MEMORY_CACHE_SIZE) {
            this.memoryCacheSize = memoryCacheSize;
        } else {
            this.setMemCacheSizePercent(0.3); // Set default memory cache size.
        }
    }

    public setMemCacheSizePercent(percent: number): void {
        if (percent < 0.05 || percent > 0.8) {
            throw new Error("percent must be between 0.05 and 0.8 (inclusive)");
        }
    }

    public getDiskCacheSize(): number {
        return this.diskCacheSize;
    }

    public setDiskCacheSize(diskCacheSize: number): void {
        if (diskCacheSize >= this.MIN_DISK_CACHE_SIZE) {
            this.diskCacheSize = diskCacheSize;
        }
    }

    public isMemoryCacheEnabled(): boolean {
        return this.memoryCacheEnabled;
    }

    public setMemoryCacheEnabled(memoryCacheEnabled: boolean): void {
        this.memoryCacheEnabled = memoryCacheEnabled;
    }

    public isDiskCacheEnabled(): boolean {
        return this.diskCacheEnabled;
    }

    public setDiskCacheEnabled(diskCacheEnabled: boolean) {
        this.diskCacheEnabled = diskCacheEnabled;
    }

    public getBitmapCacheListener(): BitmapCacheListener {
        return this.bitmapCacheListener;
    }

    public setBitmapCacheListener(bitmapCacheListener: BitmapCacheListener): void {
        this.bitmapCacheListener = bitmapCacheListener;
    }

    public setAppVersion(value: string) {
        this.appVersion = value
    }

    public getAppVersion(): string {
        return this.appVersion
    }

    ////////////////////////////////// bitmap cache management task ///////////////////////////////////////
    public clearCache(uri?: string): void {
        let CacheManagementTask = new BitmapCacheManagementTask(this);
        if (uri == null) {
            CacheManagementTask.onPostExecute(CacheManagementTask.MESSAGE_CLEAR);
        } else {
            CacheManagementTask.onPostExecute(CacheManagementTask.MESSAGE_CLEAR_BY_KEY, uri);
        }
    }

    public clearMemoryCache(uri?: string): void {
        let CacheManagementTask = new BitmapCacheManagementTask(this);
        if (uri == null) {
            CacheManagementTask.onPostExecute(CacheManagementTask.MESSAGE_CLEAR_MEMORY);
        } else {
            CacheManagementTask.onPostExecute(CacheManagementTask.MESSAGE_CLEAR_MEMORY_BY_KEY, uri);
        }
    }

    public clearDiskCache(uri?: string): void {
        let CacheManagementTask = new BitmapCacheManagementTask(this);
        if (uri == null) {
            CacheManagementTask.onPostExecute(CacheManagementTask.MESSAGE_CLEAR_DISK);
        } else {
            CacheManagementTask.onPostExecute(CacheManagementTask.MESSAGE_CLEAR_DISK_BY_KEY, uri);
        }
    }

    public flushCache(): void {
        let CacheManagementTask = new BitmapCacheManagementTask(this);
        CacheManagementTask.onPostExecute(CacheManagementTask.MESSAGE_FLUSH)
    }

    public closeCache(): void {
        let CacheManagementTask = new BitmapCacheManagementTask(this);
        CacheManagementTask.onPostExecute(CacheManagementTask.MESSAGE_CLOSE);
    }

    private initBitmapCache() {
        let CacheManagementTask = new BitmapCacheManagementTask(this);
        CacheManagementTask.onPostExecute(CacheManagementTask.MESSAGE_INIT_MEMORY_CACHE);
        CacheManagementTask.onPostExecute(CacheManagementTask.MESSAGE_INIT_DISK_CACHE);
    }
}